#include "localplayer.h"

#include <game/keymanager.h>
#include <physics/pworld.h>

#include <QDomDocument>
#include <QUdpSocket>

LocalPlayer::LocalPlayer(PWorld *world, PVector startPos, double startAngle, QString name, KeyManager *manager, QObject *parent, bool createShip) :
        Player(world, startPos, startAngle, name, parent, createShip)
{
    myKeyManager = manager;
    mySocket = 0;
}

LocalPlayer::LocalPlayer(Player *player, KeyManager *manager, PWorld *world) :
        Player(world, player->getStartPos(), player->getStartAngle(), player->getName(), world, false)
{
    setColor(player->getColor());
    myKeyManager = manager;
    mySocket = 0;
}

Qt::Key LocalPlayer::getKeyUp() const {
    return myKeyUp;
}

Qt::Key LocalPlayer::getKeyDown() const {
    return myKeyDown;
}

Qt::Key LocalPlayer::getKeyRight() const {
    return myKeyRight;
}

Qt::Key LocalPlayer::getKeyLeft() const {
    return myKeyLeft;
}

void LocalPlayer::setKeys(Qt::Key up, Qt::Key down, Qt::Key right, Qt::Key left) {
    myKeyUp = up;
    myKeyDown = down;
    myKeyRight = right;
    myKeyLeft = left;

    myKeyManager->addEvent(myKeyUp, this, SLOT(pressAccelerate()), SLOT(releaseAccelerate()));
    myKeyManager->addEvent(myKeyDown, this, SLOT(pressFire()), SLOT(releaseFire()));
    myKeyManager->addEvent(myKeyLeft, this, SLOT(pressLeft()), SLOT(releaseLeft()));
    myKeyManager->addEvent(myKeyRight, this, SLOT(pressRight()), SLOT(releaseRight()));

    myKeyManager->addEvent(myKeyUp, this, SLOT(sendAccelerate()), SLOT(sendNAccelerate()));
    myKeyManager->addEvent(myKeyDown, this, SLOT(sendFire()), SLOT(sendNFire()));
    myKeyManager->addEvent(myKeyLeft, this, SLOT(sendLeft()), SLOT(sendNLeft()));
    myKeyManager->addEvent(myKeyRight, this, SLOT(sendRight()), SLOT(sendNRight()));
}

void LocalPlayer::sendAccelerate() {
    if (!mySocket) {
        return;
    }
    QByteArray array;
    array.append(QString("<Command>\n  <Player>Accelerate</Player>\n</Command>"));
    array = qCompress(array);
    mySocket->writeDatagram(array, array.size(), myServerAddr, myPort);
}

void LocalPlayer::sendFire() {
    if (!mySocket) {
        return;
    }
    QByteArray array;
    array.append(QString("<Command>\n  <Player>Fire</Player>\n</Command>"));
    array = qCompress(array);
    mySocket->writeDatagram(array, array.size(), myServerAddr, myPort);
}

void LocalPlayer::sendLeft() {
    if (!mySocket) {
        return;
    }
    QByteArray array;
    array.append(QString("<Command>\n  <Player>Left</Player>\n</Command>"));
    array = qCompress(array);
    mySocket->writeDatagram(array, array.size(), myServerAddr, myPort);
}

void LocalPlayer::sendRight() {
    if (!mySocket) {
        return;
    }
    QByteArray array;
    array.append(QString("<Command>\n  <Player>Right</Player>\n</Command>"));
    array = qCompress(array);
    mySocket->writeDatagram(array, array.size(), myServerAddr, myPort);
}

void LocalPlayer::sendNAccelerate() {
    if (!mySocket) {
        return;
    }
    QByteArray array;
    array.append(QString("<Command>\n  <Player>NAccelerate</Player>\n</Command>"));
    array = qCompress(array);
    mySocket->writeDatagram(array, array.size(), myServerAddr, myPort);
}

void LocalPlayer::sendNFire() {
    if (!mySocket) {
        return;
    }
    QByteArray array;
    array.append(QString("<Command>\n  <Player>NFire</Player>\n</Command>"));
    array = qCompress(array);
    mySocket->writeDatagram(array, array.size(), myServerAddr, myPort);
}

void LocalPlayer::sendNLeft() {
    if (!mySocket) {
        return;
    }
    QByteArray array;
    array.append(QString("<Command>\n  <Player>NLeft</Player>\n</Command>"));
    array = qCompress(array);
    mySocket->writeDatagram(array, array.size(), myServerAddr, myPort);
}

void LocalPlayer::sendNRight() {
    if (!mySocket) {
        return;
    }
    QByteArray array;
    array.append(QString("<Command>\n  <Player>NRight</Player>\n</Command>"));
    array = qCompress(array);
    mySocket->writeDatagram(array, array.size(), myServerAddr, myPort);
}

void LocalPlayer::serialize(QDomDocument *doc, QDomElement *elem) const {
    qDebug("serialize local player");
    elem->setAttribute("type", "NetworkPlayer");
    Player::serialize(doc, elem);

    QDomElement keyUp = doc->createElement("KeyUp");
    QDomText keyUp_v = doc->createTextNode(QString("%1").arg(myKeyUp));
    keyUp.appendChild(keyUp_v);
    elem->appendChild(keyUp);

    QDomElement keyDown = doc->createElement("KeyDown");
    QDomText keyDown_v = doc->createTextNode(QString("%1").arg(myKeyDown));
    keyDown.appendChild(keyDown_v);
    elem->appendChild(keyDown);

    QDomElement keyRight = doc->createElement("KeyRight");
    QDomText keyRight_v = doc->createTextNode(QString("%1").arg(myKeyRight));
    keyRight.appendChild(keyRight_v);
    elem->appendChild(keyRight);

    QDomElement keyLeft = doc->createElement("KeyLeft");
    QDomText keyLeft_v = doc->createTextNode(QString("%1").arg(myKeyLeft));
    keyLeft.appendChild(keyLeft_v);
    elem->appendChild(keyLeft);
}

LocalPlayer *LocalPlayer::deserialize(QDomNode e, PWorld *world, KeyManager *manager) {
    Player *player = Player::deserialize(e, 0);
    LocalPlayer *localPlayer = new LocalPlayer(player, manager, world);
    delete player;

    Qt::Key keyUp = Qt::Key_No;
    Qt::Key keyDown = Qt::Key_No;
    Qt::Key keyLeft = Qt::Key_No;
    Qt::Key keyRight = Qt::Key_No;
    QDomNode n = e.firstChild();
    while (!n.isNull()) {
        QString tagname = n.toElement().tagName();
        if (tagname == "KeyUp") {
            keyUp = (Qt::Key)n.firstChild().toText().data().toInt();
        } else if (tagname == "KeyDown") {
            keyDown = (Qt::Key)n.firstChild().toText().data().toInt();
        } else if (tagname == "KeyLeft") {
            keyLeft = (Qt::Key)n.firstChild().toText().data().toInt();
        } else if (tagname == "KeyRight") {
            keyRight = (Qt::Key)n.firstChild().toText().data().toInt();
        }
        n = n.nextSibling();
    }
    localPlayer->setKeys(keyUp, keyDown, keyRight, keyLeft);

    return localPlayer;
}

QString LocalPlayer::getType() const {
    return QString("LocalPlayer");
}

void LocalPlayer::setSocket(QUdpSocket *socket, QHostAddress address, int port) {
    mySocket = socket;
    myServerAddr = address;
    myPort = port;
}
